<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>文件上传</title>
  <meta name="description" content="">
  <link rel="icon" href="https://chen-show.gitee.io/vue/favicon.ico" />
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }

    body {
      width: 100%;
      height: 100vh;
      background: #a1dddd;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    ul {
      list-style: none;
    }

    ::-webkit-scrollbar {
      width: 0px;
      height: 0px;
      background-color: #0d9696;
    }

    ::-webkit-scrollbar-track {
      box-shadow: inset 0 0 0px #0d9696;
      border-radius: 1px;
      background-color: #0d9696;
    }

    ::-webkit-scrollbar-thumb {
      border-radius: 1px;
      box-shadow: inset 0 0 0px #a1dddd;
      background-color: #a5dfdf;
    }

    video::-webkit-media-controls-current-time-display {
      display: none;
    }

    a,
    span,
    img {
      border-style: none;
      user-select: none;
      -webkit-user-drag: none;
      -webkit-user-select: none;
    }

    .upload-container-img,
    .upload-container-video {
      width: 36%;
      height: 60%;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-direction: column;
      border: 1px solid #0d9696;
      padding: 240px;
      margin: 0 25px;
      border-radius: 12px;
      box-shadow: inset 0 0 10px #0d9696;
    }

    form {
      display: flex;
      align-items: center;
      justify-content: center;
      flex-direction: column;
    }

    button {
      margin-top: 20px;
      width: 100px;
      height: 50px;
      border-radius: 5px;
      border: 1px solid #0d9696;
      background: #0d9696;
      color: #fff;
      font-size: 15px;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: all 0.3s;
    }

    button:hover {
      cursor: pointer;
      background: #a5dfdf;
      color: brown;
    }

    button a {
      color: #fff;
      text-decoration: none;
    }

    .tokenPostion {
      position: absolute;
      top: 11%;
      left: 50%;
      transform: translate(-50%, 0);
      width: 64%;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .tokenPostion input {
      width: 80%;
      height: 50px;
      border-radius: 9px;
      border: 1px solid #0d9696;
      background: #0d9696;
      color: #fff;
      font-size: 15px;
      text-indent: 5px;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: all 0.3s;
    }

    .tokenPostion button {
      margin: 0 0 0 20px;
      width: 100px;
      height: 50px;
      border-radius: 5px;
      border: 1px solid #0d9696;
      background: #0d9696;
      color: #fff;
      font-size: 15px;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: all 0.3s;
    }
  </style>
</head>

<body>
  <div class="tokenPostion">
    <input type="text" value="Bearer ">
    <button>设置token</button>
    <button><a href="/" target="_blank">接口文档</a></button>
  </div>
  <div class="upload-container-img">
    <form action="../../node/file/img" method="post" enctype="multipart/form-data">
      <input type="file" name="file" accept="image/*">
      <button type="submit">上传图片</button>
    </form>
  </div>
  <div class="upload-container-video">
    <form action="../../node/file/video" method="post" enctype="multipart/form-data">
      <input type="file" name="file" accept="video/*">
      <button type="submit">视频分片</button>
      <div class="progressBar"></div>
    </form>
  </div>
</body>
<script>
  const tokenInput = document.querySelector('.tokenPostion input');
  const tokenButton = document.querySelector('.tokenPostion button');
  const token = localStorage.getItem('token');
  tokenInput.value = token || 'Bearer ';
  const formImg = document.querySelector('.upload-container-img form');
  tokenButton.addEventListener('click', () => {
    localStorage.setItem('token', tokenInput.value);
  });

  formImg.addEventListener('submit', (e) => {
    e.preventDefault();
    const dom = formImg.querySelector('input[type="file"]');
    if (!dom.files[0].type.startsWith('image/')) return alert('只支持图片上传！');
    const xhr = new XMLHttpRequest();
    const formData = new FormData();
    formData.append('file', dom.files[0], dom.files[0].name);
    xhr.open('POST', '../../node/file/img', true);
    xhr.setRequestHeader("token", `${localStorage.getItem('token')}`);
    xhr.onload = function () {
      if (xhr.status === 200) {
        const data = JSON.parse(xhr.response);
        if (data.code === 200) {
          dom.value = '';
          alert('上传成功');
        } else {
          if (data.code === 401) tokenInput.value = '';
          alert(`${data.msg}`);
        }
      } else {
        alert('An error occurred!');
      }
    };
    xhr.send(formData);
  });

  const formVideo = document.querySelector('.upload-container-video form');
  formVideo.addEventListener('submit', (e) => {
    e.preventDefault();
    const fileInput = formVideo.querySelector('input[type="file"]');
    const file = fileInput.files[0];
    if (file.size < 1024 * 1024 * 0.3) return alert('文件大小不超过0.3MB,请使用文件上传！');
    if (!file.type.startsWith('video/')) return alert('只支持视频上传！');
    const progressBar = document.querySelector('.progressBar');
    progressBar.textContent = '0%';

    const chunkSize = 1024 * 1024 * 0.3; // 每个分片大小为.3MB
    let start = 0;
    let index = 0;
    let end = Math.min(chunkSize, file.size);
    const totalChunks = Math.ceil(file.size / chunkSize);
    uploadNextChunk();
    function uploadNextChunk () {
      if (start < file.size) {
        const chunk = file.slice(start, end);
        uploadChunk(chunk, index, totalChunks).then((res) => {
          if (res.code === 200 || res.code === 201 || res.code === 204) {
            start = end;
            end = Math.min(start + chunkSize, file.size);
            index++;
            uploadNextChunk();
            const num = Number((start / file.size * 100).toFixed(2));
            progressBar.textContent = num + '%';
            if ((index + 1) === totalChunks) progressBar.textContent = '正在合并...';
            else if (num === 100) progressBar.textContent = '文件上传完成！';
          } else {
            if (res.code === 401) tokenInput.value = '';
            alert(`${res.msg}`);
          }
        }).catch((error) => {
          progressBar.textContent = '上传文件错误：' + error;
        });
      }
    }

    function uploadChunk (chunk, index, totalChunks) { // 上传分片
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open('POST', '../../node/file/video', true); // upload文件上传，video视频上传
        xhr.setRequestHeader("token", `${localStorage.getItem('token')}`);
        xhr.onload = function () {
          if (xhr.status === 200) {
            resolve(JSON.parse(xhr.response));
          } else {
            reject(new Error(xhr.statusText));
          }
        };
        xhr.onerror = function () {
          reject(new Error('服务异常'));
        };
        const formData = new FormData();
        formData.append('file', chunk);
        formData.append('indexChunks', index);
        formData.append('fileName', file.name);
        formData.append('totalChunks', totalChunks);
        xhr.send(formData);
      });
    }

  });
</script>
<script src="https://chen-show.gitee.io/vue/js/canvas-nest.min.js" type="text/javascript" color="0,200,188"
  opacity="0.6" zIndex="1" count="55"></script>

</html>